package org.benjamin.lending.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.benjamin.lending.domain.entity.MemberInfo;
import org.benjamin.lending.domain.entity.MemberStatus;
import org.benjamin.lending.domain.entity.RechargeLog;
import org.benjamin.lending.domain.entity.SubmitRealName;
import org.benjamin.lending.domain.entity.TransactRequest;
import org.benjamin.lending.domain.entity.TransactRequest.Status;
import org.benjamin.lending.domain.entity.WithdrawalsLog;
import org.benjamin.lending.domain.form.RealNameForm;
import org.benjamin.lending.domain.form.RechargeForm;
import org.benjamin.lending.domain.form.TransactForm;
import org.benjamin.lending.domain.form.WithdrawForm;
import org.benjamin.lending.domain.transact.BasicOutBean;
import org.benjamin.lending.repository.MemberInfoRepository;
import org.benjamin.lending.repository.MemberStatusRepository;
import org.benjamin.lending.repository.SubmitRealNameRepository;
import org.benjamin.lending.repository.TransactRequestRepository;
import org.benjamin.lending.service.MemberInfoService;
import org.benjamin.lending.service.RechargeService;
import org.benjamin.lending.service.TransactService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;

import com.fasterxml.jackson.databind.ObjectMapper;

public abstract class DefaultTransactServiceImpl implements TransactService {
	
	private Logger logger = LogManager.getLogger();
	
	@Autowired
	protected MemberInfoService memberInfoService;
	
	@Autowired
	private MemberInfoRepository memberInfoRepository;
	
	@Autowired
	private MemberStatusRepository memberStatusRepository;
	
	@Autowired
	private SubmitRealNameRepository submitRealNameRepository;
	
	@Autowired
	private RechargeService rechargeService;
	
	@Autowired
	private TransactRequestRepository transactRequestRepository;
	
	@Override
	public BasicOutBean realNameRequest(String username,RealNameForm form) {
		SubmitRealName submitRealName = this.submitRealNameRepository.findByRealNameAndIdNumber(form.getUserName(), form.getIdNumber());
		if(submitRealName != null && !submitRealName.isResult()) {
			throw new IllegalArgumentException("当前表单已经提交过，校验结果不匹配");
		}
		MemberInfo memberInfo = this.memberInfoRepository.findByUsername(username);
		MemberStatus memberStatus = this.memberStatusRepository.findOne(memberInfo.getId());
		if(memberStatus == null) {
			memberStatus = new MemberStatus();
			memberStatus.setId(memberInfo.getId());
			
		}
		memberStatus.setRealName(2);
		this.memberStatusRepository.save(memberStatus);
		
		return null;
	}
	
	
	@Override
	public TransactRequest realNameResponse(Map<String, Object> responseMap,String requestId){
		TransactRequest request = this.transactRequestRepository.findOne(requestId);
		try {
			RealNameForm nameForm = new ObjectMapper().readValue(request.getOrigParam(), RealNameForm.class);
			MemberInfo memberInfo = request.getMemberInfo();
			memberInfo.setRealName(nameForm.getUserName());
			memberInfo.setIdNumber(nameForm.getIdNumber());
			this.memberInfoRepository.save(memberInfo);
			MemberStatus memberStatus = this.memberStatusRepository.findOne(memberInfo.getId());
			if(memberStatus == null) {
				memberStatus = new MemberStatus();
				memberStatus.setId(memberInfo.getId());
			}
			memberStatus.setRealName(1);
			this.memberStatusRepository.save(memberStatus);
			request.setStatus(Status.COMPLETE);
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
			throw new IllegalArgumentException(e.getMessage());
		}
		return request;
	}

	@Override
	public BasicOutBean registerAccessRequest(String username) {
		BasicOutBean basicOutBean = new BasicOutBean();
		return basicOutBean;
	}

	@Override
	public BasicOutBean userRechargeRequest(RechargeForm rechargeForm, String username) {
		RechargeLog rechargeLog = this.rechargeService.userRecgargeRequest(rechargeForm, username);
		BasicOutBean basicOutBean = new BasicOutBean();
		basicOutBean.setResultData(rechargeLog);
		basicOutBean.setMemberInfo(rechargeLog.getMemberInfo());
		return basicOutBean;
	}
	
	

	@Override
	public void userRechargeResponse(Integer rechargeId, boolean finshSuccess, Map<String, Object> responesMap) {
		if(finshSuccess) {
			this.rechargeService.finshSuccess(rechargeId);
		}else {
			this.rechargeService.finshFaill(rechargeId);
		}
	}

	

	@Override
	public BasicOutBean withdrawRequest(String username, WithdrawForm withdrawFrom, BigDecimal serviceCharge) {
		
		BasicOutBean basicOutBean = new BasicOutBean();		
		MemberInfo memberInfo = this.memberInfoRepository.findByUsername(username);
		basicOutBean.setMemberInfo(memberInfo);
		WithdrawalsLog withdrawalsLog = this.memberInfoService.withdrawApply(memberInfo,withdrawFrom,serviceCharge);
		basicOutBean.setResultData(withdrawalsLog);
		basicOutBean.getTransactRequest().setMoney(withdrawFrom.getAmount());
		logger.info("用户提现记录已经完成保存到数据库中");
		return basicOutBean;
	}


	@Override
	public Page<TransactRequest> findRequestLogsPage(final TransactForm transactForm, Pageable pageable) {
		Specification<TransactRequest> specification = new Specification<TransactRequest>() {
			
			@Override
			public Predicate toPredicate(Root<TransactRequest> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				if(StringUtils.isNotBlank(transactForm.getRequestId())) {
					list.add(cb.equal(root.get("id").as(String.class), transactForm.getRequestId()));
				}
				if(StringUtils.isNotBlank(transactForm.getUsername())) {
					list.add(cb.like(root.get("memberInfo").get("username").as(String.class), transactForm.getUsername()));
				}
				Predicate[] predicates = new Predicate[list.size()];
				
				return query.where(list.toArray(predicates)).getGroupRestriction();
			}
		};
		return this.transactRequestRepository.findAll(specification,pageable);
	}

	@Override
	public TransactRequest findRequestDetails(String requestId) {
		return this.transactRequestRepository.findOne(requestId);
	}

}
